package com.sanchunhui.psc.ui.activity

import android.os.Bundle
import com.sanchunhui.psc.R
import kotlinx.android.synthetic.main.activity_main.*
import android.content.Context
import android.content.Intent
import android.os.Build
import android.text.TextUtils
import android.util.Log
import android.util.TypedValue
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.sanchunhui.psc.ui.fragment.*
import com.sanchunhui.psc.utils.StatusBarUtil.StatusBarUtil
import java.util.*
import com.ashokvarma.bottomnavigation.BottomNavigationBar
import com.eightbitlab.rxbus.Bus
import com.sanchunhui.psc.common.AppManager
import com.sanchunhui.psc.event.NoticeMessageEvent
import com.sanchunhui.psc.utils.AlarmsObservable
import com.zhengsr.zplib.ZPermission
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.*
import org.jetbrains.anko.toast
import android.Manifest
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.content.pm.PackageManager
import android.graphics.Point
import android.location.LocationManager
import android.view.MotionEvent
import com.noober.menu.FloatMenu
import com.sanchunhui.psc.common.BaseApplication
import com.sanchunhui.psc.data.protocol.Team
import com.sanchunhui.psc.event.TeamHandleEvent
import kotlinx.android.synthetic.main.header.*
import org.json.JSONObject
import androidx.core.app.ComponentActivity.ExtraData
import androidx.core.content.ContextCompat.getSystemService
import android.icu.lang.UCharacter.GraphemeClusterBreak.T
import android.location.Location
import android.location.LocationListener
import androidx.annotation.RequiresApi
import com.device.id.DeviceIdUtils
import com.google.gson.Gson
import com.sanchunhui.psc.data.protocol.Pagination
import com.sanchunhui.psc.event.DeviceMessagePublishEvent
import com.trello.rxlifecycle.RxLifecycle.bindUntilEvent
import java.util.stream.IntStream

/**
 * @Author zyx
 * @Date 2021/4/08-10:00
 * @Dscribe
 */

class MainActivity : BaseActivity(), ProjectTeamsFragment.OnListFragmentInteractionListener {

    private lateinit var mqttClient: MqttAndroidClient
    private lateinit var userName : String // 用户名
    private lateinit var passWord: String // 密码

    // GPS
    private var latitude : Double = 0.0 // 经度
    private var longitude  : Double = 0.0 // 纬度
    private lateinit var locationManager: LocationManager
    //定义一个权限Code，用来识别Location权限
    private val LOCATION_PERMISSION = 1
    //使用匿名内部类创建了LocationListener的实例
    val locationListener = object : LocationListener {
        override fun onProviderDisabled(provider: String?) {
            toast("GPS已关闭")
        }

        override fun onProviderEnabled(provider: String?) {
            toast("GPS已打开")
        }

        override fun onLocationChanged(location: Location?) {
//            toast("变化了")
            latitude = location!!.latitude
            longitude = location.longitude
        }

        override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    }

    companion object {
        const val TAG = "AndroidMqttClient"

        init {
            // Used to load the 'native-lib' library on application startup.
            System.loadLibrary("native-lib")
        }
    }

    //视图触摸中心点
    private val point = Point()

    private var pressTime:Long = 0
    //Fragment 栈管理
    private val mStack = Stack<Fragment>()
    //消息Fragment
    private val mMessageFragment by lazy { MessageFragment() }
    //组织Fragment
    //项目负责人界面
    private val mProjectTeamsFragment by lazy { ProjectTeamsFragment() }
    //小组长界面
    private val mTeamMemberFragment by lazy { TeamMembersFragment() }
    //资讯Fragment
    private val mInforFragment by lazy { InformationFragment() }
    //我的Fragment
    private val mMeFragment by lazy { MeFragment() }

    private external fun stringFromJNI(): String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //判断设备是否有虚拟按键，如果有增加paddingBottom=50dp
//        if (checkDeviceHasNavigationBar(this)) {
//            ll_main_activity.setPadding(0, 0, 0, 50.dp2px())
//        }
//        setStatusBar()
        initFragment()
        initBottomNav()
        changeFragment(0)
        initObserve()
        initMQTT()
        requestPermission()

        val bluetooth = BluetoothAdapter.getDefaultAdapter()
        if (bluetooth == null) {
            Toast.makeText(this@MainActivity, "您的设备未找到蓝牙驱动！!", Toast.LENGTH_SHORT).show()
            finish()
        } else {
            if (!bluetooth.isEnabled) {
                startActivityForResult(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1)
            }
        }

        //对lateinit的变量进行初始化
        locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        //如果手机的SDK版本使用新的权限模型，检查是否获得了位置权限，如果没有就申请位置权限，如果有权限就刷新位置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val hasLocationPermission =
                checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
            if (hasLocationPermission != PackageManager.PERMISSION_GRANTED) {
                //requestPermissions是异步执行的
                requestPermissions(
                    arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION)
            } else {

            }
        } else {

        }

        // 调用c函数
//        var text = stringFromJNI()
//        Toast.makeText(this, text, Toast.LENGTH_SHORT).show()

    }


    @RequiresApi(Build.VERSION_CODES.M)
    override fun onPause() {
        super.onPause()
        val hasLocationPermission = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
        if ((locationManager != null) && ((hasLocationPermission == PackageManager.PERMISSION_GRANTED))) {
            locationManager.removeUpdates(locationListener)
        }
    }

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onResume() {
        //挂上LocationListener, 在状态变化时刷新位置显示，因为requestPermissionss是异步执行的，所以要先确认是否有权限
        super.onResume()
        val hasLocationPermission = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
        if ((locationManager != null) && ((hasLocationPermission == PackageManager.PERMISSION_GRANTED))) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0F, locationListener)
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000,0F, locationListener)
        }
    }

    //申请下位置权限后，要刷新位置信息
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == LOCATION_PERMISSION) {
//            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//                toast("获取了位置权限")
//            }
        }
    }

    //获取位置信息
    @RequiresApi(Build.VERSION_CODES.M)
    fun getLocation(locationManager: LocationManager): Location? {
        var location: Location? = null
        if (this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
            toast("没有位置权限")
        }
        else if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            toast("没有打开GPS")
        }
        else {
            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
            if (location == null) {
                toast("位置信息为空")
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
                if (location == null) {
                    toast("网络位置信息也为空")
                } else {
                    toast("当前使用网络位置")
                }
            }
        }
        return location
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 1){
            if (resultCode == Activity.RESULT_CANCELED){
                Toast.makeText(this@MainActivity, "请您不要拒绝开启蓝牙，否则应用无法运行", Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    /*
       初始化MQTT
     */
    fun initMQTT() {
        val user = BaseApplication.mUser
        userName = ""
        passWord = "${user.token}"
        connect(this)
    }

    /*
       初始化Fragment栈管理
    */
    private fun initFragment() {
        // 根据登录用户角色显示对应的Fragment, role:0成员，1组长，2项目负责人
        val user = BaseApplication.mUser
        val manager = supportFragmentManager.beginTransaction()
        manager.add(R.id.mContaier,mMessageFragment)
        if (user.role == 2) {
            manager.add(R.id.mContaier,mProjectTeamsFragment)
        } else if (user.role == 1) {
            manager.add(R.id.mContaier,mTeamMemberFragment)
        }
        manager.add(R.id.mContaier,mInforFragment)
        manager.add(R.id.mContaier,mMeFragment)
        manager.commit()
        mStack.add(mMessageFragment)
        if (user.role == 2) {
            mStack.add(mProjectTeamsFragment)
        } else if (user.role == 1) {
            mStack.add(mTeamMemberFragment)
        }
        mStack.add(mInforFragment)
        mStack.add(mMeFragment)
    }

    /*
        初始化底部导航切换事件
     */
    private fun initBottomNav(){
        mBottomNavBar.setTabSelectedListener(object :BottomNavigationBar.OnTabSelectedListener{
            override fun onTabReselected(position: Int) {

            }

            override fun onTabUnselected(position: Int) {

            }

            override fun onTabSelected(position: Int) {
                changeFragment(position)
            }
        })

        mBottomNavBar.checkMsgBadge(false)
    }

    /*
        切换Tab，切换对应的Fragment
     */
    private fun changeFragment(position: Int) {
        val manager = supportFragmentManager.beginTransaction()
        for (fragment in mStack){
            manager.hide(fragment)
        }

        manager.show(mStack[position])
        manager.commit()
    }

    /*
        初始化监听，消息数量变化及消息标签是否显示
     */
    private fun initObserve(){
        Bus.observe<DeviceMessagePublishEvent>().subscribe {
            run {
                val invoiceAdditionalAttribute = mutableMapOf<String, String>()
                invoiceAdditionalAttribute.put("warnStatus",it.warnStatus.toString())
                invoiceAdditionalAttribute.put("temperature", it.temperature.toString())
                invoiceAdditionalAttribute.put("altitude", it.altitude.toString())
                val user = BaseApplication.mUser
                publish("w/${user.project_id}/${user.team_id}/${user.id}", invoiceAdditionalAttribute.toString(),1, false)
//                val gson = Gson()
//                val json = gson.toJson(invoiceAdditionalAttribute)
            }
        }
//        Bus.observe<UpdateMessageSizeEvent>()
//            .subscribe {
//                loadCartSize()
//            }.registerInBus(this)
//
//        Bus.observe<MessageBadgeEvent>()
//            .subscribe {
//                    t: MessageBadgeEvent ->
//                run {
//                    mBottomNavBar.checkMsgBadge(t.isVisible)
//                }
//            }.registerInBus(this)
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (ev.action == MotionEvent.ACTION_DOWN) {
            point.x = ev.rawX.toInt()
            point.y = ev.rawY.toInt()
        }
        return super.dispatchTouchEvent(ev)
    }

    override fun onListFragmentInteraction(team: Team) {
        val floatMenu = FloatMenu(this@MainActivity)
        floatMenu.items("设置分组名称", "移除该分组")
        floatMenu.setOnItemClickListener { v, position ->
            Bus.send(TeamHandleEvent(position, team))
        }
        floatMenu.show(point)
    }

    /*
         取消Bus事件监听
     */
    override fun onDestroy() {
        super.onDestroy()
        Bus.unregister(this)
    }

    /*
        重写Back事件，双击退出
     */
    override fun onBackPressed() {
        val time = System.currentTimeMillis()
        if (time - pressTime > 2000){
            toast("再按一次退出程序")
            pressTime = time
        } else{
            AppManager.instance.exitApp(this)
        }
    }

    //  Android透明状态栏与状态栏文字颜色更改
    private fun setStatusBar() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (isUseFullScreenMode()) {
                StatusBarUtil.transparencyBar(this)
            } else {
                StatusBarUtil.setStatusBarColor(this, getStatusBarColor())
            }

            if (isUseBlackFontWithStatusBar()) {
                StatusBarUtil.setLightStatusBar(this, true, isUseFullScreenMode())
            }
        }
    }

//    /**
//     * 是否设置成透明状态栏，即就是全屏模式
//     */
//    protected fun isUseFullScreenMode(): Boolean {
//        return false
//    }
//
//    /**
//     * 更改状态栏颜色，只有非全屏模式下有效
//     */
//    protected fun getStatusBarColor(): Int {
//        return R.color.nav_bar
//    }
//
//    /**
//     * 是否改变状态栏文字颜色为黑色，默认为黑色
//     */
//    protected fun isUseBlackFontWithStatusBar(): Boolean {
//        return true
//    }
//
//    fun jumpActivity(clazz: Class<*>) {
//        startActivity(Intent(this, clazz))
//    }

    /*
    * 把转化功能添加到Int类中作为扩展函数
    * */
    fun Int.dp2px(): Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            toFloat(), resources.displayMetrics
        ).toInt()
    }

    // 获取是否存在NavigationBar
    fun checkDeviceHasNavigationBar(context: Context): Boolean {
        var hasNavigationBar = false
        val rs = context.getResources()
        val id = rs.getIdentifier("config_showNavigationBar", "bool", "android")
        if (id > 0) {
            hasNavigationBar = rs.getBoolean(id)
        }
        try {
            val systemPropertiesClass = Class.forName("android.os.SystemProperties")
            val m = systemPropertiesClass.getMethod("get", String::class.java)
            val navBarOverride = m.invoke(systemPropertiesClass, "qemu.hw.mainkeys") as String
            if ("1" == navBarOverride) {
                hasNavigationBar = false
            } else if ("0" == navBarOverride) {
                hasNavigationBar = true
            }
        } catch (e: Exception) {

        }
        return hasNavigationBar
    }

    /*
        连接 MQTT 服务器
    */
    fun connect(context: Context) {
        val deviceId = DeviceIdUtils.getDeviceId(this@MainActivity)
        val user = BaseApplication.mUser
//        val serverURI = "tcp://q93ee3d3.cn.emqx.cloud:11264"
        val serverURI = "tcp://safety.3chh.cn:1883"
        mqttClient = MqttAndroidClient(context, serverURI, "U${user.id}")
        mqttClient.setCallback(object : MqttCallback {
            override fun messageArrived(topic: String?, message: MqttMessage?) {
                var type = topic!![0].toString() // 判断消息类型
                if (type.equals("w")) { // 报警消息
                    val extras:String? = message.toString()
//                    var payload : String = String(message!!.getPayload())
//                    val gson = Gson()
//                    pagination = Gson().fromJson(paginationStr, Pagination::class.java)
                    AlarmsObservable.instance.newMsgComing(extras!!)
                }
                Log.d(TAG, "Receive message: ${message.toString()} from topic: $topic")
            }

            override fun connectionLost(cause: Throwable?) {
                Log.d(TAG, "Connection lost ${cause.toString()}")
            }

            override fun deliveryComplete(token: IMqttDeliveryToken?) {

            }
        })

        val options = MqttConnectOptions()
        options.mqttVersion = MqttConnectOptions.MQTT_VERSION_3_1_1 //选择MQTT版本
        options.setAutomaticReconnect(true) // 断开后，是否自动连接
        options.setCleanSession(true) //是否清空客户端的连接记录。若为true，则断开后，broker将自动清除该客户端连接信息
        options.setConnectionTimeout(60) // 设置超时时间，单位：秒
        options.setKeepAliveInterval(5) //心跳时间，单位为秒。即多长时间确认一次Client端是否在线
        options.setUserName(userName) //设置用户名。跟Client ID不同。用户名可以看做权限等级
        options.setPassword(passWord.toCharArray()) //设置登录密码
        options.maxInflight = 10 //允许同时发送几条消息（未收到broker确认信息）默认是10
        try {
            mqttClient.connect(options, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "Connection success")

                    //连接成功发送过来的通知，连接成功才能去订阅消息。
                    //如果需要一次订阅多个主题，需要用for循环去订阅多个
//                    subscribe("a/${user.projectId}/#",0)
//                    subscribe("TA",0)
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Connection failure")
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    /*
    * 创建 MQTT 订阅
    * 订阅 topic
    * */
    fun subscribe(topic: String, qos: Int = 1) {
        try {
            mqttClient.subscribe(topic, qos, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "Subscribed to $topic")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Failed to subscribe $topic")
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    /*
    * 取消订阅
    * 取消订阅 topic
    * */
    fun unsubscribe(topic: String) {
        try {
            mqttClient.unsubscribe(topic, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "Unsubscribed to $topic")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Failed to unsubscribe $topic")
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    /*
    * 发布消息
    * */
    fun publish(topic: String, msg: String, qos: Int = 1, retained: Boolean = false) {
        // w/pid/tid/uid
        try {
            val message = MqttMessage()
            message.payload = msg.toByteArray()
            message.qos = qos
            message.isRetained = retained
            mqttClient.publish(topic, message, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "$msg published to $topic")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Failed to publish $msg to $topic")
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    /*
    * 断开 MQTT 连接
    * */
    fun disconnect() {
        try {
            mqttClient.disconnect(null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "Disconnected")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Failed to disconnect")
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    private fun requestPermission() {
        ZPermission.with(this)
            .permissions(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.BLUETOOTH_ADMIN
            ).request { isAllGranted, deniedLists ->
                if (!isAllGranted){
                    Toast.makeText(this, "需要开启权限才能运行应用", Toast.LENGTH_SHORT).show()
                    finish()
                }
            }

        //在 Android 10 还需要开启 gps
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val lm: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
            if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){
                Toast.makeText(this@MainActivity, "请您先开启gps,否则蓝牙不可用", Toast.LENGTH_SHORT).show()
            }
        }

    }

}
